$.app({
    data: {
        value: "",
        contentDom:null,
        toolbarVisible:'static',//'static','auto','hide'
        height:"300px" //指定高度
    },
    //命令接口参见
    //https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
    onBold:function (e) {
        this.exec("bold");
    },
    onItalic:function (e) {
        this.exec("italic");
    },
    onUnderline:function (e) {
        this.exec("underline");
    },
    onStrikeout:function (e) {
        this.exec("strikeThrough");
    },
    onListUl:function (e) {
        this.exec("insertUnorderedList");
    },
    onListOl:function (e) {
        this.exec("insertOrderedList");
    },
    onHead1:function (e) {
        this.exec('formatBlock', '<h1>');
    },
    onHead2:function (e) {
        this.exec('formatBlock', '<h2>');
    },
    onHead3:function (e) {
        this.exec('formatBlock', '<h3>');
    },
    onHead4:function (e) {
        this.exec('formatBlock', '<h4>');
    },
    onHead5:function (e) {
        this.exec('formatBlock', '<h5>');
    },
    onParagragh:function (e) {
        this.exec('formatBlock', '<p>');
    },
    onHorzLine:function (e) {
        this.exec('insertHorizontalRule');
    },
    onQuote:function (e) {
        this.exec('formatBlock', '<blockquote>');
    },
    onCode:function (e) {
        this.exec('formatBlock', '<pre>');
    },
    exec : function (command, value) {
        //this.data.content.focus();
        document.execCommand(command, false, value || null);
        this._save();
    },
    _save:function () {
        var me = this;
        var val = me.data.contentDom.getValue();
        if( me.data.value != val ){
            me.data.value = val;
            me.dataThrough({
                value : val
            },false);
        }
    },
    onKeypress:function (e) {
        //this._save();
    },
    onBlur:function (e) {
        $.log("save---->");
        this._save();
    }
});
/*
var defaultParagraphSeparatorString = 'defaultParagraphSeparator';
var formatBlock = 'formatBlock';
var addEventListener = function (parent, type, listener) {
    parent.addEventListener(type, listener);
};
var appendChild = function (parent, child) {
    parent.appendChild(child);
};

var createElement = function (tag) {
    document.createElement(tag);
};
var queryCommandState = function (command) {
    document.queryCommandState(command);
};
var queryCommandValue = function (command) {
    document.queryCommandValue(command);
};

var exec = function (command, value) {
    document.execCommand(command, false, value);
};

var defaultActions = {
    bold: {
        icon: '<b>B</b>',
        title: 'Bold',
        state: function () {
            queryCommandState('bold');
        },
        result: function () {
            exec('bold');
        }
    },
    italic: {
        icon: '<i>I</i>',
        title: 'Italic',
        state: function () {
            queryCommandState('italic')
        },
        result: function () {
            exec('italic')
        }
    },
    underline: {
        icon: '<u>U</u>',
        title: 'Underline',
        state: function () {
            queryCommandState('underline')
        },
        result: function () {
            exec('underline')
        }
    },
    strikethrough: {
        icon: '<strike>S</strike>',
        title: 'Strike-through',
        state: function () {
            queryCommandState('strikeThrough')
        },
        result: function () {
            exec('strikeThrough')
        }
    },
    heading1: {
        icon: '<b>H<sub>1</sub></b>',
        title: 'Heading 1',
        result: function () {
            exec(formatBlock, '<h1>')
        }
    },
    heading2: {
        icon: '<b>H<sub>2</sub></b>',
        title: 'Heading 2',
        result: function () {
            exec(formatBlock, '<h2>')
        }
    },
    paragraph: {
        icon: '&#182;',
        title: 'Paragraph',
        result: function () {
            exec(formatBlock, '<p>')
        }
    },
    quote: {
        icon: '&#8220; &#8221;',
        title: 'Quote',
        result: function () {
            exec(formatBlock, '<blockquote>')
        }
    },
    olist: {
        icon: '&#35;',
        title: 'Ordered List',
        result: function () {
            exec('insertOrderedList')
        }
    },
    ulist: {
        icon: '&#8226;',
        title: 'Unordered List',
        result: function () {
            exec('insertUnorderedList')
        }
    },
    code: {
        icon: '&lt;/&gt;',
        title: 'Code',
        result: function () {
            exec(formatBlock, '<pre>')
        }
    },
    line: {
        icon: '&#8213;',
        title: 'Horizontal Line',
        result: function () {
            exec('insertHorizontalRule')
        }
    },
    link: {
        icon: '&#128279;',
        title: 'Link',
        result: function () {
            var url = window.prompt('Enter the link URL');
            if (url) exec('createLink', url)
        }
    },
    image: {
        icon: '&#128247;',
        title: 'Image',
        result: function () {
            var url = window.prompt('Enter the image URL');
            if (url) exec('insertImage', url)
        }
    }
};

var defaultClasses = {
    actionbar: 'pell-actionbar',
    button: 'pell-button',
    content: 'pell-content',
    selected: 'pell-button-selected'
};

var init = function (settings) {
    var actions = settings.actions
        ? (
            settings.actions.map(function (action) {
                if (typeof action === 'string') return defaultActions[action]
                else if (defaultActions[action.name]) return {...defaultActions[action.name],
            ...
                action
            }
                return action
            })
        )
        : Object.keys(defaultActions).map(function (action) {
            defaultActions[action]
        )
}

    var classes = {...defaultClasses, .
..
    settings.classes
}

    var defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div';

    var actionbar = createElement('div');
    actionbar.className = classes.actionbar;
    appendChild(settings.element, actionbar);

    const content = settings.element.content = createElement('div');
    content.contentEditable = true;
    content.className = classes.content
    content.oninput = function ({target: {firstChild}}) {
        if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`)
        else if (content.innerHTML === '<br>') content.innerHTML = '';
        settings.onChange(content.innerHTML)
    };
    content.onkeydown = function (event) {
        if (event.key === 'Tab') {
            event.preventDefault()
        } else if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
            setTimeout(function () {
                exec(formatBlock, `<${defaultParagraphSeparator}>`)
            }, 0);
        }
    };
    appendChild(settings.element, content);

    actions.forEach(function (action) {
        const button = createElement('button');
        button.className = classes.button;
        button.innerHTML = action.icon;
        button.title = action.title;
        button.setAttribute('type', 'button');
        button.onclick = function () {
            action.result() && content.focus()
        }

        if (action.state) {
            const handler = function () {
                button.classList[action.state() ? 'add' : 'remove'](classes.selected)
            }
            addEventListener(content, 'keyup', handler)
            addEventListener(content, 'mouseup', handler)
            addEventListener(button, 'click', handler)
        }

        appendChild(actionbar, button)
    });

    if (settings.styleWithCSS) exec('styleWithCSS');
    exec(defaultParagraphSeparatorString, defaultParagraphSeparator);

    return settings.element
}

*/
